package com.ssy.lingxi.member.merchant.serviceimpl.web;

import com.ssy.lingxi.common.constant.member.MemberTypeEnum;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.common.utils.DateTimeUtil;
import com.ssy.lingxi.member.merchant.api.constant.MemberRelationTypeEnum;
import com.ssy.lingxi.member.merchant.entity.*;
import com.ssy.lingxi.member.merchant.model.constant.*;
import com.ssy.lingxi.member.merchant.model.vo.basic.request.NamePageVO;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.request.*;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.response.*;
import com.ssy.lingxi.member.merchant.model.vo.maintenance.response.MemberDetailCreditComplainSummaryVO;
import com.ssy.lingxi.member.merchant.repository.MemberComplaintRepository;
import com.ssy.lingxi.member.merchant.repository.MemberRelationRepository;
import com.ssy.lingxi.member.merchant.repository.MemberUserRepository;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberCacheService;
import com.ssy.lingxi.member.merchant.service.web.IMemberComplaintService;
import com.ssy.lingxi.member.merchant.utils.FileObjectUtil;
import com.ssy.lingxi.member.merchant.utils.NumberUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 会员投诉与建议服务实现类
 * @author yzc
 * @version 2.0.0
 * @date 2021/5/17
 */
@Service
public class MemberComplaintServiceImpl implements IMemberComplaintService {
    @Resource
    private IBaseMemberCacheService memberCacheService;

    @Resource
    private MemberComplaintRepository memberComplaintRepository;

    @Resource
    private MemberRelationRepository memberRelationRepository;

    @Resource
    private MemberUserRepository memberUserRepository;

    @Override
    public Wrapper<List<StatusVO>> listMemberComplaintStatus(HttpHeaders headers) {
        List<StatusVO> statusVOList = Stream.of(MemberComplaintStatusEnum.values()).map(e -> {
            StatusVO statusVO = new StatusVO();
            statusVO.setCode(e.getCode());
            statusVO.setMessage(e.getMessage());
            return statusVO;
        }).collect(Collectors.toList());

        return Wrapper.success(statusVOList);
    }

    @Override
    public Wrapper<PageData<UpperMemberQueryVO>> pageMembers(HttpHeaders headers, NamePageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("id").ascending());
        Specification<MemberRelationDO> specification = (Specification<MemberRelationDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("subMemberId").as(Long.class), loginUser.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("subRoleId").as(Long.class), loginUser.getMemberRoleId()));
            list.add(criteriaBuilder.notEqual(root.get("relType").as(Integer.class), MemberRelationTypeEnum.PLATFORM.getCode()));
            if (org.springframework.util.StringUtils.hasLength(pageVO.getName())) {
                Join<MemberRelationDO, MemberDO> memberJoin = root.join("member", JoinType.LEFT);
                list.add(criteriaBuilder.like(memberJoin.get("name").as(String.class), "%" + pageVO.getName().trim() + "%"));
            }
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        Page<MemberRelationDO> pageList = memberRelationRepository.findAll(specification, page);
        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.stream().map(p -> {
            UpperMemberQueryVO queryVO = new UpperMemberQueryVO();
            queryVO.setMemberId(p.getMemberId());
            queryVO.setRoleId(p.getRoleId());
            queryVO.setUpperName(p.getMember().getName());
            queryVO.setRoleName(p.getRole().getRoleName());
            queryVO.setMemberTypeName(MemberTypeEnum.getCodeMessage(p.getRole().getMemberType().getTypeEnum()));
            queryVO.setLevel(p.getLevelRight().getLevel());
            queryVO.setLevelTag(p.getLevelRight().getLevelTag());
            return queryVO;
        }).collect(Collectors.toList())));
    }

    @Override
    public Wrapper<PageData<MemberUpperComplaintPageQueryVO>> pageUpperMemberComplaint(HttpHeaders headers, MemberComplaintPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);

        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("createTime").descending());

        Page<MemberComplaintDO> pageList = memberComplaintRepository.findAll((Specification<MemberComplaintDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();
            predicateList.add(cb.equal(root.get("roleId"), loginUser.getMemberRoleId()));

            Join<MemberComplaintDO, MemberDO> memberJoin = root.join("member", JoinType.LEFT);
            predicateList.add(cb.equal(memberJoin.get("id"), loginUser.getMemberId()));

            if (StringUtils.hasLength(pageVO.getName())) {
                Join<MemberComplaintDO, MemberDO> subMemberJoin = root.join("subMember", JoinType.LEFT);
                predicateList.add(cb.like(subMemberJoin.get("name").as(String.class), "%" + pageVO.getName().trim() + "%"));
            }

            if (StringUtils.hasLength(pageVO.getSubject())) {
                predicateList.add(cb.like(root.get("subject"), "%" + pageVO.getSubject() + "%"));
            }

            if (Objects.nonNull(pageVO.getEventTimeStart())) {
                LocalDateTime startDate = DateTimeUtil.parseDateTime(pageVO.getEventTimeStart());
                predicateList.add(cb.greaterThanOrEqualTo(root.get("eventTime"), startDate));
            }

            if (Objects.nonNull(pageVO.getEventTimeEnd())) {
                LocalDateTime endDate = DateTimeUtil.parseDateTime(pageVO.getEventTimeEnd());
                predicateList.add(cb.lessThanOrEqualTo(root.get("eventTime"), endDate));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return cb.and(predicateList.toArray(p));
        }, page);

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(memberComplaintDO -> {
            MemberUpperComplaintPageQueryVO queryVO = new MemberUpperComplaintPageQueryVO();
            queryVO.setId(memberComplaintDO.getId());
            queryVO.setType(memberComplaintDO.getType());
            queryVO.setTypeName(MemberComplaintTypeEnum.getCodeMessage(memberComplaintDO.getType()));
            queryVO.setClassify(memberComplaintDO.getClassify());
            queryVO.setClassifyName(MemberComplaintClassifyEnum.getCodeMessage(memberComplaintDO.getClassify()));
            queryVO.setStatus(memberComplaintDO.getStatus());
            queryVO.setStatusName(MemberComplaintStatusEnum.getCodeMessage(memberComplaintDO.getStatus()));
            queryVO.setSubject(memberComplaintDO.getSubject());
            queryVO.setSubMemberId(memberComplaintDO.getSubMember().getId());
            queryVO.setSubRoleId(memberComplaintDO.getSubRoleId());
            queryVO.setName(memberComplaintDO.getSubMember().getName());
            queryVO.setByUserId(Objects.isNull(memberComplaintDO.getByUser()) ? 0L : memberComplaintDO.getByUser().getId());
            queryVO.setByUserName(Objects.isNull(memberComplaintDO.getByUser()) ? memberComplaintDO.getByUserEditName() : memberComplaintDO.getByUser().getName());
            queryVO.setByUserPhone(Objects.isNull(memberComplaintDO.getByUser()) ? memberComplaintDO.getByUserEditPhone() : memberComplaintDO.getByUser().getPhone());
            queryVO.setEventTime(DateTimeUtil.formatDateTime(memberComplaintDO.getEventTime()));
            queryVO.setHandleTime(DateTimeUtil.formatDateTime(memberComplaintDO.getHandleTime()));
            queryVO.setSubmitOrUpdateOrDelete(MemberComplaintStatusEnum.WAIT_SUBMIT.getCode().equals(memberComplaintDO.getStatus()));
            queryVO.setHandle(MemberComplaintStatusEnum.WAIT_HANDLE.getCode().equals(memberComplaintDO.getStatus()));

            return queryVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 会员信息 - 会员信用 - 会员投诉记录汇总
     *
     * @param upperMember 上级会员
     * @param roleId      上级会员角色Id
     * @param subMember   下级会员
     * @param subRoleId   下级会员角色Id
     * @return 汇总结果
     */
    @Override
    public Wrapper<MemberDetailCreditComplainSummaryVO> summaryUpperMemberComplaints(MemberDO upperMember, Long roleId, MemberDO subMember, Long subRoleId) {
        List<MemberComplaintDO> complaintDOList = memberComplaintRepository.findAll((Specification<MemberComplaintDO>) (root, query, cb) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(cb.equal(root.get("member").as(MemberDO.class), upperMember));
            list.add(cb.equal(root.get("roleId").as(Long.class), roleId));
            list.add(cb.equal(root.get("subMember").as(MemberDO.class), subMember));
            list.add(cb.equal(root.get("subRoleId").as(Long.class), subRoleId));
            Predicate[] p = new Predicate[list.size()];
            return cb.and(list.toArray(p));
        });

        MemberDetailCreditComplainSummaryVO summaryVO = new MemberDetailCreditComplainSummaryVO();
        for (MemberComplaintDO memberComplaintDO : complaintDOList) {
            long diffDays = DateTimeUtil.diffDays(memberComplaintDO.getEventTime(), LocalDateTime.now());
            if (diffDays <= 7) {
                summaryVO.setLast7days(summaryVO.getLast7days() + 1);
            }

            if (diffDays <= 30) {
                summaryVO.setLast30days(summaryVO.getLast30days() + 1);
            }

            if (diffDays <= 180) {
                summaryVO.setLast180days(summaryVO.getLast180days() + 1);
            }

            if (diffDays > 180) {
                summaryVO.setBefore180days(summaryVO.getBefore180days() + 1);
            }
        }

        summaryVO.setSum(summaryVO.getLast180days() + summaryVO.getBefore180days());

        return Wrapper.success(summaryVO);
    }

    /**
     * 会员信息 - 会员信用 - 分页查询会员投诉记录
     *
     * @param upperMember 上级会员
     * @param roleId      上级会员角色Id
     * @param subMember   下级会员
     * @param subRoleId   下级会员角色Id
     * @param current     当前页
     * @param pageSize    每页行数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberCreditComplaintPageQueryVO>> pageUpperMemberComplaint(MemberDO upperMember, Long roleId, MemberDO subMember, Long subRoleId, int current, int pageSize) {
        Pageable page = PageRequest.of(current - 1, pageSize, Sort.by("createTime").descending());
        Page<MemberComplaintDO> pageList = memberComplaintRepository.findAll((Specification<MemberComplaintDO>) (root, query, cb) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(cb.equal(root.get("member").as(MemberDO.class), upperMember));
            list.add(cb.equal(root.get("roleId").as(Long.class), roleId));
            list.add(cb.equal(root.get("subMember").as(MemberDO.class), subMember));
            list.add(cb.equal(root.get("subRoleId").as(Long.class), subRoleId));
            Predicate[] p = new Predicate[list.size()];
            return cb.and(list.toArray(p));
        }, page);

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(memberComplaintDO -> {
            MemberCreditComplaintPageQueryVO queryVO = new MemberCreditComplaintPageQueryVO();
            queryVO.setId(memberComplaintDO.getId());
            queryVO.setType(memberComplaintDO.getType());
            queryVO.setTypeName(MemberComplaintTypeEnum.getCodeMessage(memberComplaintDO.getType()));
            queryVO.setClassify(memberComplaintDO.getClassify());
            queryVO.setClassifyName(MemberComplaintClassifyEnum.getCodeMessage(memberComplaintDO.getClassify()));
            queryVO.setSubject(memberComplaintDO.getSubject());
            queryVO.setName(memberComplaintDO.getMember().getName());
            queryVO.setEventTime(DateTimeUtil.formatDateTime(memberComplaintDO.getEventTime()));
            queryVO.setHandleTime(memberComplaintDO.getHandleTime() == null ? "" : DateTimeUtil.formatDateTime(memberComplaintDO.getHandleTime()));
            queryVO.setResult(StringUtils.hasLength(memberComplaintDO.getHandleResult()) ? memberComplaintDO.getHandleResult() : "");
            return queryVO;
        }).collect(Collectors.toList())));
    }

    @Override
    public Wrapper<PageData<MemberSubComplaintPageQueryVO>> pageSubMemberComplaint(HttpHeaders headers, MemberComplaintPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);

        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("createTime").descending());

        Page<MemberComplaintDO> pageList = memberComplaintRepository.findAll((Specification<MemberComplaintDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();

            predicateList.add(cb.equal(root.get("subRoleId"), loginUser.getMemberRoleId()));
            Predicate andPre = cb.and(cb.equal(root.get("status"), MemberComplaintStatusEnum.COMPLETE_HANDLE.getCode()), cb.equal(root.get("complaintType"), MemberComplaintComplaintTypeEnum.UPPER.getCode()));
            Predicate orPre = cb.or(andPre, cb.equal(root.get("complaintType"), MemberComplaintComplaintTypeEnum.SUB.getCode()));
            predicateList.add(orPre);

            Join<MemberComplaintDO, MemberDO> subMemberJoin = root.join("subMember", JoinType.LEFT);
            predicateList.add(cb.equal(subMemberJoin.get("id"), loginUser.getMemberId()));


            if (StringUtils.hasLength(pageVO.getName())) {
                Join<MemberRectifyDO, MemberDO> memberJoin = root.join("member", JoinType.LEFT);
                predicateList.add(cb.like(memberJoin.get("name").as(String.class), "%" + pageVO.getName().trim() + "%"));
            }

            if (StringUtils.hasLength(pageVO.getSubject())) {
                predicateList.add(cb.like(root.get("subject"), "%" + pageVO.getSubject() + "%"));
            }

            if (Objects.nonNull(pageVO.getEventTimeStart())) {
                LocalDateTime startDate = DateTimeUtil.parseDateTime(pageVO.getEventTimeStart());
                predicateList.add(cb.greaterThanOrEqualTo(root.get("eventTime"), startDate));
            }

            if (Objects.nonNull(pageVO.getEventTimeEnd())) {
                LocalDateTime endDate = DateTimeUtil.parseDateTime(pageVO.getEventTimeEnd());
                predicateList.add(cb.lessThanOrEqualTo(root.get("eventTime"), endDate));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return cb.and(predicateList.toArray(p));
        }, page);

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(memberComplaintDO -> {
            MemberSubComplaintPageQueryVO queryVO = new MemberSubComplaintPageQueryVO();
            queryVO.setId(memberComplaintDO.getId());
            queryVO.setType(memberComplaintDO.getType());
            queryVO.setTypeName(MemberComplaintTypeEnum.getCodeMessage(memberComplaintDO.getType()));
            queryVO.setClassify(memberComplaintDO.getClassify());
            queryVO.setClassifyName(MemberComplaintClassifyEnum.getCodeMessage(memberComplaintDO.getClassify()));
            queryVO.setStatus(memberComplaintDO.getStatus());
            queryVO.setStatusName(MemberComplaintStatusEnum.getCodeMessage(memberComplaintDO.getStatus()));
            queryVO.setSubject(memberComplaintDO.getSubject());
            queryVO.setMemberId(memberComplaintDO.getMember().getId());
            queryVO.setRoleId(memberComplaintDO.getRoleId());
            queryVO.setUpperName(memberComplaintDO.getMember().getName());
            queryVO.setByUserId(Objects.isNull(memberComplaintDO.getByUser()) ? 0L : memberComplaintDO.getByUser().getId());
            queryVO.setByUserName(Objects.isNull(memberComplaintDO.getByUser()) ? memberComplaintDO.getByUserEditName() : memberComplaintDO.getByUser().getName());
            queryVO.setByUserPhone(Objects.isNull(memberComplaintDO.getByUser()) ? memberComplaintDO.getByUserEditPhone() : memberComplaintDO.getByUser().getPhone());
            queryVO.setEventTime(DateTimeUtil.formatDateTime(memberComplaintDO.getEventTime()));
            queryVO.setHandleTime(DateTimeUtil.formatDateTime(memberComplaintDO.getHandleTime()));
            queryVO.setSubmitOrUpdateOrDelete(MemberComplaintStatusEnum.WAIT_SUBMIT.getCode().equals(memberComplaintDO.getStatus()));

            return queryVO;
        }).collect(Collectors.toList())));
    }

    @Override
    public Wrapper<MemberComplaintUpperVO> getUpperMemberComplaint(HttpHeaders headers, CommonIdVO idVO) {
        memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberComplaintDO memberComplaintDO = memberComplaintRepository.findById(idVO.getId()).orElse(null);
        if (Objects.isNull(memberComplaintDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        MemberComplaintUpperVO memberComplaintUpperVO = new MemberComplaintUpperVO();
        memberComplaintUpperVO.setId(memberComplaintDO.getId());
        memberComplaintUpperVO.setType(memberComplaintDO.getType());
        memberComplaintUpperVO.setTypeName(MemberComplaintTypeEnum.getCodeMessage(memberComplaintDO.getType()));
        memberComplaintUpperVO.setClassify(memberComplaintDO.getClassify());
        memberComplaintUpperVO.setClassifyName(MemberComplaintClassifyEnum.getCodeMessage(memberComplaintDO.getClassify()));
        memberComplaintUpperVO.setSubject(memberComplaintDO.getSubject());
        memberComplaintUpperVO.setSubMemberId(memberComplaintDO.getSubMember().getId());
        memberComplaintUpperVO.setSubRoleId(memberComplaintDO.getSubRoleId());
        memberComplaintUpperVO.setName(memberComplaintDO.getSubMember().getName());
        memberComplaintUpperVO.setByUserId(Objects.isNull(memberComplaintDO.getByUser()) ? 0L : memberComplaintDO.getByUser().getId());
        memberComplaintUpperVO.setByUserName(Objects.isNull(memberComplaintDO.getByUser()) ? memberComplaintDO.getByUserEditName() : memberComplaintDO.getByUser().getName());
        memberComplaintUpperVO.setByUserPhone(Objects.isNull(memberComplaintDO.getByUser()) ? memberComplaintDO.getByUserEditPhone() : memberComplaintDO.getByUser().getPhone());
        memberComplaintUpperVO.setEventTime(DateTimeUtil.formatDateTime(memberComplaintDO.getEventTime()));
        memberComplaintUpperVO.setEventDesc(memberComplaintDO.getEventDesc());
        memberComplaintUpperVO.setEventSuggest(memberComplaintDO.getEventSuggest());
        memberComplaintUpperVO.setAttachments(FileObjectUtil.toVOList(memberComplaintDO.getAttachments()));
        memberComplaintUpperVO.setHandleUserId(Objects.isNull(memberComplaintDO.getHandleUser()) ? 0L : memberComplaintDO.getHandleUser().getId());
        memberComplaintUpperVO.setHandleUserName(Objects.isNull(memberComplaintDO.getHandleUser()) ? memberComplaintDO.getHandleUserEditName() : memberComplaintDO.getHandleUser().getName());
        memberComplaintUpperVO.setHandleUserPhone(Objects.isNull(memberComplaintDO.getHandleUser()) ? memberComplaintDO.getHandleUserEditPhone() : memberComplaintDO.getHandleUser().getPhone());
        memberComplaintUpperVO.setHandleResult(memberComplaintDO.getHandleResult());
        memberComplaintUpperVO.setHandleTime(DateTimeUtil.formatDateTime(memberComplaintDO.getHandleTime()));
        memberComplaintUpperVO.setHandleAttachments(FileObjectUtil.toVOList(memberComplaintDO.getHandleAttachments()));

        return Wrapper.success(memberComplaintUpperVO);
    }

    @Override
    public Wrapper<MemberComplaintSubVO> getSubMemberComplaint(HttpHeaders headers, CommonIdVO idVO) {
        memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberComplaintDO memberComplaintDO = memberComplaintRepository.findById(idVO.getId()).orElse(null);
        if (Objects.isNull(memberComplaintDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        MemberComplaintSubVO memberComplaintUpperVO = new MemberComplaintSubVO();
        memberComplaintUpperVO.setId(memberComplaintDO.getId());
        memberComplaintUpperVO.setType(memberComplaintDO.getType());
        memberComplaintUpperVO.setTypeName(MemberComplaintTypeEnum.getCodeMessage(memberComplaintDO.getType()));
        memberComplaintUpperVO.setClassify(memberComplaintDO.getClassify());
        memberComplaintUpperVO.setClassifyName(MemberComplaintClassifyEnum.getCodeMessage(memberComplaintDO.getClassify()));
        memberComplaintUpperVO.setSubject(memberComplaintDO.getSubject());
        memberComplaintUpperVO.setMemberId(memberComplaintDO.getMember().getId());
        memberComplaintUpperVO.setRoleId(memberComplaintDO.getRoleId());
        memberComplaintUpperVO.setUpperName(memberComplaintDO.getMember().getName());
        memberComplaintUpperVO.setByUserId(Objects.isNull(memberComplaintDO.getByUser()) ? 0L : memberComplaintDO.getByUser().getId());
        memberComplaintUpperVO.setByUserName(Objects.isNull(memberComplaintDO.getByUser()) ? memberComplaintDO.getByUserEditName() : memberComplaintDO.getByUser().getName());
        memberComplaintUpperVO.setByUserPhone(Objects.isNull(memberComplaintDO.getByUser()) ? memberComplaintDO.getByUserEditPhone() : memberComplaintDO.getByUser().getPhone());
        memberComplaintUpperVO.setEventTime(DateTimeUtil.formatDateTime(memberComplaintDO.getEventTime()));
        memberComplaintUpperVO.setEventDesc(memberComplaintDO.getEventDesc());
        memberComplaintUpperVO.setEventSuggest(memberComplaintDO.getEventSuggest());
        memberComplaintUpperVO.setAttachments(FileObjectUtil.toVOList(memberComplaintDO.getAttachments()));
        memberComplaintUpperVO.setHandleUserId(Objects.isNull(memberComplaintDO.getHandleUser()) ? 0L : memberComplaintDO.getHandleUser().getId());
        memberComplaintUpperVO.setHandleUserName(Objects.isNull(memberComplaintDO.getHandleUser()) ? memberComplaintDO.getHandleUserEditName() : memberComplaintDO.getHandleUser().getName());
        memberComplaintUpperVO.setHandleUserPhone(Objects.isNull(memberComplaintDO.getHandleUser()) ? memberComplaintDO.getHandleUserEditPhone() : memberComplaintDO.getHandleUser().getPhone());
        memberComplaintUpperVO.setHandleResult(memberComplaintDO.getHandleResult());
        memberComplaintUpperVO.setHandleTime(DateTimeUtil.formatDateTime(memberComplaintDO.getHandleTime()));
        memberComplaintUpperVO.setHandleAttachments(FileObjectUtil.toVOList(memberComplaintDO.getHandleAttachments()));

        return Wrapper.success(memberComplaintUpperVO);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> addUpperMemberComplaint(HttpHeaders headers, MemberComplaintUpperAddVO addVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberRelationDO relationDO = memberRelationRepository.findFirstByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(loginUser.getMemberId(), loginUser.getMemberRoleId(), addVO.getSubMemberId(), addVO.getSubRoleId());
        if (relationDO == null || !relationDO.getMemberId().equals(loginUser.getMemberId()) || !relationDO.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        MemberComplaintDO memberComplaintDO = new MemberComplaintDO();

        // 系统用户和编辑用户的差异保存
        if (!NumberUtil.isNullOrZero(addVO.getByUserId())) {
            MemberUserDO userDO = memberUserRepository.findById(addVO.getByUserId()).orElse(null);
            if (userDO == null) {
                return Wrapper.fail(ResponseCode.MC_MS_MEMBER_USER_DOES_NOT_EXIST);
            }
            memberComplaintDO.setByUser(userDO);
        } else {
            memberComplaintDO.setByUserEditName(addVO.getByUserEditName());
            memberComplaintDO.setByUserEditPhone(addVO.getByUserEditPhone());
        }

        memberComplaintDO.setStatus(MemberComplaintStatusEnum.WAIT_SUBMIT.getCode());
        memberComplaintDO.setType(addVO.getType());
        memberComplaintDO.setComplaintType(MemberComplaintComplaintTypeEnum.UPPER.getCode());
        memberComplaintDO.setClassify(addVO.getClassify());
        memberComplaintDO.setSubject(addVO.getSubject());
        memberComplaintDO.setMember(relationDO.getMember());
        memberComplaintDO.setRoleId(relationDO.getRoleId());
        memberComplaintDO.setSubMember(relationDO.getSubMember());
        memberComplaintDO.setSubRoleId(relationDO.getSubRoleId());
        memberComplaintDO.setEventTime(DateTimeUtil.parseDateTime(addVO.getEventTime()));
        memberComplaintDO.setEventDesc(addVO.getEventDesc());
        memberComplaintDO.setEventSuggest(addVO.getEventSuggest());
        memberComplaintDO.setAttachments(FileObjectUtil.toBOList(addVO.getAttachments()));
        memberComplaintDO.setCreateTime(LocalDateTime.now());

        memberComplaintRepository.saveAndFlush(memberComplaintDO);

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> addSubMemberComplaint(HttpHeaders headers, MemberComplaintSubAddVO addVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberRelationDO relationDO = memberRelationRepository.findFirstByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(addVO.getMemberId(), addVO.getRoleId(), loginUser.getMemberId(), loginUser.getMemberRoleId());
        if (relationDO == null || !relationDO.getSubMember().getId().equals(loginUser.getMemberId()) || !relationDO.getSubRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        MemberComplaintDO memberComplaintDO = new MemberComplaintDO();

        // 系统用户和编辑用户的差异保存
        if (!NumberUtil.isNullOrZero(addVO.getByUserId())) {
            MemberUserDO userDO = memberUserRepository.findById(addVO.getByUserId()).orElse(null);
            if (userDO == null) {
                return Wrapper.fail(ResponseCode.MC_MS_MEMBER_USER_DOES_NOT_EXIST);
            }

            memberComplaintDO.setByUser(userDO);
        } else {
            memberComplaintDO.setByUserEditName(addVO.getByUserEditName());
            memberComplaintDO.setByUserEditPhone(addVO.getByUserEditPhone());
        }

        memberComplaintDO.setStatus(MemberComplaintStatusEnum.WAIT_SUBMIT.getCode());
        memberComplaintDO.setType(addVO.getType());
        memberComplaintDO.setComplaintType(MemberComplaintComplaintTypeEnum.SUB.getCode());
        memberComplaintDO.setClassify(addVO.getClassify());
        memberComplaintDO.setSubject(addVO.getSubject());
        memberComplaintDO.setMember(relationDO.getMember());
        memberComplaintDO.setRoleId(relationDO.getRoleId());
        memberComplaintDO.setSubMember(relationDO.getSubMember());
        memberComplaintDO.setSubRoleId(relationDO.getSubRoleId());
        memberComplaintDO.setEventTime(DateTimeUtil.parseDateTime(addVO.getEventTime()));
        memberComplaintDO.setEventDesc(addVO.getEventDesc());
        memberComplaintDO.setEventSuggest(addVO.getEventSuggest());
        memberComplaintDO.setAttachments(FileObjectUtil.toBOList(addVO.getAttachments()));
        memberComplaintDO.setCreateTime(LocalDateTime.now());

        memberComplaintRepository.saveAndFlush(memberComplaintDO);

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> updateUpperMemberComplaint(HttpHeaders headers, MemberComplaintUpperUpdateVO addVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberComplaintDO memberComplaintDO = memberComplaintRepository.findById(addVO.getId()).orElse(null);
        if (Objects.isNull(memberComplaintDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        if (!MemberComplaintStatusEnum.WAIT_SUBMIT.getCode().equals(memberComplaintDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        MemberRelationDO relationDO = memberRelationRepository.findFirstByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(loginUser.getMemberId(), loginUser.getMemberRoleId(), addVO.getSubMemberId(), addVO.getSubRoleId());
        if (relationDO == null || !relationDO.getMemberId().equals(loginUser.getMemberId()) || !relationDO.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        // 系统用户和编辑用户的差异保存
        if (!NumberUtil.isNullOrZero(addVO.getByUserId())) {
            MemberUserDO userDO = memberUserRepository.findById(addVO.getByUserId()).orElse(null);
            if (userDO == null) {
                return Wrapper.fail(ResponseCode.MC_MS_MEMBER_USER_DOES_NOT_EXIST);
            }

            memberComplaintDO.setByUser(userDO);
            memberComplaintDO.setByUserEditName(null);
            memberComplaintDO.setByUserEditPhone(null);
        } else {
            memberComplaintDO.setByUser(null);
            memberComplaintDO.setByUserEditName(addVO.getByUserEditName());
            memberComplaintDO.setByUserEditPhone(addVO.getByUserEditPhone());
        }

        memberComplaintDO.setType(addVO.getType());
        memberComplaintDO.setClassify(addVO.getClassify());
        memberComplaintDO.setSubject(addVO.getSubject());
        memberComplaintDO.setMember(relationDO.getMember());
        memberComplaintDO.setRoleId(relationDO.getRoleId());
        memberComplaintDO.setSubMember(relationDO.getSubMember());
        memberComplaintDO.setSubRoleId(relationDO.getSubRoleId());
        memberComplaintDO.setEventTime(DateTimeUtil.parseDateTime(addVO.getEventTime()));
        memberComplaintDO.setEventDesc(addVO.getEventDesc());
        memberComplaintDO.setEventSuggest(addVO.getEventSuggest());
        memberComplaintDO.setAttachments(FileObjectUtil.toBOList(addVO.getAttachments()));

        memberComplaintRepository.saveAndFlush(memberComplaintDO);

        return Wrapper.success();
    }

    @Override
    public Wrapper<Void> updateSubMemberComplaint(HttpHeaders headers, MemberComplaintSubUpdateVO addVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberComplaintDO memberComplaintDO = memberComplaintRepository.findById(addVO.getId()).orElse(null);
        if (Objects.isNull(memberComplaintDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        if (!MemberComplaintStatusEnum.WAIT_SUBMIT.getCode().equals(memberComplaintDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        MemberRelationDO relationDO = memberRelationRepository.findFirstByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(addVO.getMemberId(), addVO.getRoleId(), loginUser.getMemberId(), loginUser.getMemberRoleId());
        if (relationDO == null || !relationDO.getSubMember().getId().equals(loginUser.getMemberId()) || !relationDO.getSubRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        // 系统用户和编辑用户的差异保存
        if (!NumberUtil.isNullOrZero(addVO.getByUserId())) {
            MemberUserDO userDO = memberUserRepository.findById(addVO.getByUserId()).orElse(null);
            if (userDO == null) {
                return Wrapper.fail(ResponseCode.MC_MS_MEMBER_USER_DOES_NOT_EXIST);
            }

            memberComplaintDO.setByUser(userDO);
            memberComplaintDO.setByUserEditName(null);
            memberComplaintDO.setByUserEditPhone(null);
        } else {
            memberComplaintDO.setByUser(null);
            memberComplaintDO.setByUserEditName(addVO.getByUserEditName());
            memberComplaintDO.setByUserEditPhone(addVO.getByUserEditPhone());
        }

        memberComplaintDO.setType(addVO.getType());
        memberComplaintDO.setClassify(addVO.getClassify());
        memberComplaintDO.setSubject(addVO.getSubject());
        memberComplaintDO.setMember(relationDO.getMember());
        memberComplaintDO.setRoleId(relationDO.getRoleId());
        memberComplaintDO.setSubMember(relationDO.getSubMember());
        memberComplaintDO.setSubRoleId(relationDO.getSubRoleId());
        memberComplaintDO.setEventTime(DateTimeUtil.parseDateTime(addVO.getEventTime()));
        memberComplaintDO.setEventDesc(addVO.getEventDesc());
        memberComplaintDO.setEventSuggest(addVO.getEventSuggest());
        memberComplaintDO.setAttachments(FileObjectUtil.toBOList(addVO.getAttachments()));

        memberComplaintRepository.saveAndFlush(memberComplaintDO);

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> deleteMemberComplaint(HttpHeaders headers, CommonIdVO idVO) {
        memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberComplaintDO memberComplaintDO = memberComplaintRepository.findById(idVO.getId()).orElse(null);
        if (Objects.isNull(memberComplaintDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        if (!MemberComplaintStatusEnum.WAIT_SUBMIT.getCode().equals(memberComplaintDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        memberComplaintRepository.deleteById(memberComplaintDO.getId());

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> submitMemberComplaint(HttpHeaders headers, CommonIdVO idVO) {
        memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberComplaintDO memberComplaintDO = memberComplaintRepository.findById(idVO.getId()).orElse(null);
        if (Objects.isNull(memberComplaintDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        if (!MemberComplaintStatusEnum.WAIT_SUBMIT.getCode().equals(memberComplaintDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        memberComplaintDO.setStatus(MemberComplaintStatusEnum.WAIT_HANDLE.getCode());
        memberComplaintRepository.saveAndFlush(memberComplaintDO);

        return Wrapper.success();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Wrapper<Void> handleMemberComplaint(HttpHeaders headers, MemberComplaintHandleVO handleVO) {
        memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberComplaintDO memberComplaintDO = memberComplaintRepository.findById(handleVO.getId()).orElse(null);
        if (Objects.isNull(memberComplaintDO)) {
            return Wrapper.fail(ResponseCode.MC_MS_RECORDS_DON_T_EXIST);
        }

        if (!MemberComplaintStatusEnum.WAIT_HANDLE.getCode().equals(memberComplaintDO.getStatus())) {
            return Wrapper.fail(ResponseCode.MC_MS_DATA_STATUS_INCORRECT_OPERATE_INVALID);
        }

        // 系统用户和编辑用户的差异保存
        if (!NumberUtil.isNullOrZero(handleVO.getHandleUserId())) {
            MemberUserDO userDO = memberUserRepository.findById(handleVO.getHandleUserId()).orElse(null);
            if (userDO == null) {
                return Wrapper.fail(ResponseCode.MC_MS_MEMBER_USER_DOES_NOT_EXIST);
            }

            memberComplaintDO.setHandleUser(userDO);
            memberComplaintDO.setHandleUserEditName(null);
            memberComplaintDO.setHandleUserEditPhone(null);
        } else {
            memberComplaintDO.setHandleUser(null);
            memberComplaintDO.setHandleUserEditName(handleVO.getHandleUserEditName());
            memberComplaintDO.setHandleUserEditPhone(handleVO.getHandleUserEditPhone());
        }

        memberComplaintDO.setStatus(MemberComplaintStatusEnum.COMPLETE_HANDLE.getCode());
        memberComplaintDO.setHandleTime(DateTimeUtil.parseDateTime(handleVO.getHandleTime()));
        memberComplaintDO.setHandleResult(handleVO.getHandleResult());
        memberComplaintDO.setHandleAttachments(FileObjectUtil.toBOList(handleVO.getHandleAttachments()));

        memberComplaintRepository.saveAndFlush(memberComplaintDO);

        return Wrapper.success();
    }
}
